module HplProducts.Hephaestus where

import FeatureModel.Types
import FeatureModel.Parsers.GenericParser 
--import CK.Parsers.XML.XmlConfigurationParser
import qualified BasicTypes as Core
import System.Directory
import System.FilePath
import Maybe 

import HplProducts.HephaestusTypes
import HplAssets.Hephaestus
 
data TransformationModel = UndefinedTransformation
                         | HephaestusTransformation HephaestusTransformation
 
transform ::
            TransformationModel -> SPLModel -> InstanceModel -> InstanceModel
transform (UndefinedTransformation) _ _ = undefined
transform (HephaestusTransformation x0) x1 x2
  = transformHpl  x0 x1 x2
 
mkEmptyInstance :: FeatureConfiguration -> InstanceModel
mkEmptyInstance fc
  = InstanceModel{featureConfiguration = fc, hpl = emptyHpl}
 
type ConfigurationKnowledge = [ConfigurationItem]
 
data ConfigurationItem = ConfigurationItem{expr ::
                                           FeatureExpression,
                                           transformations :: [TransformationModel]}
 
build ::
        FeatureModel ->
          FeatureConfiguration ->
            ConfigurationKnowledge -> SPLModel -> InstanceModel
build fm fc ck spl = stepRefinement ts spl emptyInstance
  where emptyInstance = mkEmptyInstance fc
        ts = tasks ck fc
 
tasks ::
        ConfigurationKnowledge ->
          FeatureConfiguration -> [TransformationModel]
tasks ck fc
  = concat [transformations c | c <- ck, eval fc (expr c)]
 
stepRefinement ::
                 [TransformationModel] -> SPLModel -> InstanceModel -> InstanceModel
stepRefinement [] splModel instanceModel = instanceModel
stepRefinement (t : ts) splModel instanceModel
  = stepRefinement ts splModel (transform t splModel instanceModel)
 
data ExportModel = UndefinedExport
                 | ExportHephaestusDoc 
 
export :: ExportModel -> FilePath -> InstanceModel -> IO ()
export (UndefinedExport) _ _ = undefined
export (ExportHephaestusDoc) x1 x2 = exportHplToDoc (x1++".doc") (hpl x2)
 
lstExport :: [ExportModel]
lstExport = [ExportHephaestusDoc]


-- temporary
criaCK :: ConfigurationKnowledge
criaCK = [ ConfigurationItem { } ]


-- the function Main it will be in another module out here
main :: IO()
main = do 
--  let cmds = lstCommandsBegin ++ lstCommandsAssets ++ lstCommandsEnd in 
--    sequence_ cmds
--  return ()

 cDir <- getCurrentDirectory
 let ns = normalizedSchema cDir
     
 f <- getLine	             -- read the name of the project file 
 s <- readFile f             -- read the file contents
 let l = lines s             -- split the content in several lines

 -- read all properties 
 let ps  = map fromJust (filter (isJust) (map readPropertyValue l))
 
-- retrieve the specific property values we are interested in
 let n = fromJust (findPropertyValue "name" ps)
 let f = fromJust (findPropertyValue "feature-model" ps)
 let i = fromJust (findPropertyValue "instance-model" ps) 
 let c = fromJust (findPropertyValue "configuration-model" ps)
 let t = fromJust (findPropertyValue "target-dir" ps)
 --let u = fromJust (findPropertyValue "usecase-model" ps)
          
 (Core.Success fm) <- parseFeatureModel  ((ns fmSchema), snd f) FMPlugin
 --(Core.Success cm) <- parseConfigurationKnowledge (ns ckSchema) (snd c)
 let cm = criaCK -- temporary !!!
 (Core.Success im) <- parseInstanceModel (ns fcSchema) (snd i)  
 --(Core.Success ucpl) <- parseUseCaseFile (ns ucSchema) (snd u)  
 
 let fc = FeatureConfiguration im
 let spl = SPLModel { }
 let product = build fm fc cm spl
 let out = (outputFile (snd t) (snd n)) -- a função "export" vai gerar a extensão (.tex, .xml, etc) do nome de output dado por "n" em Properties
 
 -- isso também é variabilidade Saída do UCM. Criar também saída para o BPM
 --let ucp = ucm product
 --exportUcmToLatex (out ++ ".tex") ucp
 
 sequence_ [export x out product | x<-lstExport]
 --sequence_ (map export lstExport)
 
 print $ "Ok, the output file was genarated at: " ++ out
  
 return()
 
 
-----------------------------------------------------------------------------------------
-- definitions brought from module Main.hs of Hephaestus 
-----------------------------------------------------------------------------------------       
type PropertyValue = (String, String)

fmSchema :: String 
fmSchema = "schema_feature-model.rng"

fcSchema :: String
fcSchema = "schema_feature-configuration.rng"

ckSchema :: String 
ckSchema = "schema-configuration-knowledge.rng"

normalizedSchema:: FilePath -> String -> FilePath
normalizedSchema cDir sch = cDir </> sch 

outputFile :: FilePath -> String -> FilePath
outputFile  f n = f </> n 
--outputFile :: FilePath -> String -> FilePath
--outputFile  f n = f </> (n ++ ".tex") 

-- given a String s, it returns just a property, 
-- if s matches "key=value". Otherwise, it returns 
-- Nothing.
readPropertyValue :: String -> Maybe PropertyValue
readPropertyValue s =
 let p = break (== '=') s
 in case p of 
     ([], _) -> Nothing
     (k , v) -> Just (k, tail v)  

findPropertyValue:: String -> [PropertyValue] -> Maybe PropertyValue  
findPropertyValue k [] = Nothing
findPropertyValue k (x:xs) =   
 if (k == fst x) then Just x
 else findPropertyValue k xs    
 
